﻿using System.Collections.Generic;
using OpenCompiler.AST;
using OpenCompiler.Scanning;

namespace OpenCompiler
{
	public class Parser
	{
		private int _tokenIndex;
		private Token[] _tokens;

		public void Parse(List<Token> tokenList)
		{
			this._tokens = tokenList.ToArray();
			this._tokenIndex = 0;

			this.Result = this.Parse();
		}

		public Statement Result { get; private set; }

		private void HandleModifiers(object currentToken)
		{
			if (currentToken is Formatting)
			{
				var format = (Formatting)currentToken;
				if (format == Formatting.ScopeStart ||
					format == Formatting.LineEnd)
				{
					ModifierState.Reset();
				}
			}
		}

		private Statement HandleKeywords(Statement currentStatement, Token currentTokenInfo, object currentToken)
		{
			var element = Keywords.GetLanguageElementFromKeyword((Keyword)currentToken);

			var tokensUsed = 0;
			var result = element.Generate(currentStatement,this._tokens, this._tokenIndex, out tokensUsed);
			if (null != result)
			{
				result.TokenInfo = currentTokenInfo;
			}
			this._tokenIndex += tokensUsed;
			return result;
		}

		private Statement Parse()
		{
			var root = Statement.File("");
			var result = this.Parse(root);

			return result;
		}

		private Statement Parse(Statement statement)
		{
			
			var currentTokenInfo = this._tokens[this._tokenIndex];
			var currentToken = currentTokenInfo.ActualToken;

			HandleModifiers(currentToken);

			if (currentToken is Keyword)
			{
				statement = this.HandleKeywords(statement, currentTokenInfo, currentToken);
			}

			// Handle fields

			// Handle properties
			//   Directly handle property body

			// Handle methods
			//   Directly handle method body

			this._tokenIndex++;

			if (this._tokenIndex < this._tokens.Length)
			{
				//var sequence = new Sequence {First = result, Second = this.Parse()};
				//result = sequence;
				statement = this.Parse(statement);
			}
			return statement;
		}
	}
}
